package com.qianxun.modular.doc.rest;

import com.qianxun.framework.common.util.Md5Util;
import com.qianxun.modular.base.Result;
import com.qianxun.modular.doc.common.AbstractDocBaseService;
import com.qianxun.modular.doc.entity.Doc;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文档前端控制器
 *
 * @author Admin
 */
@RequestMapping("/doc")
@RestController
public class DocController extends AbstractDocBaseService {

    @RequestMapping("/init")
    public Result initDocList() {
        String outerRootName = getOuterRootName();
        File dir = new File(outerRootName);
        List<Doc> result = commonDealFileList(dir, buildDocIdByName(outerRootName));
        return Result.success(result);
    }

    @RequestMapping("/subList")
    public Result getSubDocList(String docId, String path, String sort) {
        if (StringUtils.isBlank(path)) {
            path = getOuterRootName();
        }

        if (StringUtils.isBlank(docId)) {
            docId = buildDocIdByName(path);
        }
        File dir = new File(path);
        List<Doc> result = commonDealFileList(dir, docId);
        if (null != sort) {
            result = sortDocList(result, sort);
        }
        return Result.success(result);
    }

    @RequestMapping("/getDoc")
    public Result getDoc(String docId, Integer docType, String name, String path) {
        if (StringUtils.isBlank(path)) {
            path = getOuterRootName();
        }

        File baseFile = new File(path);
        Doc doc = new Doc();
        doc.setId(docId);
        doc.setType(0);
        doc.setName("");
        doc.setPath("");

        if (baseFile.exists()) {
            doc.setType(baseFile.isDirectory() ? 2 : 1);
            doc.setName(StringUtils.isBlank(name) ? "" : name);
            doc.setPath(path);
            String filePath = baseFile.getPath().replace("\\", "/");
            String outerRootName = getOuterRootName().replace("\\", "/");
            String replace = filePath.replace(outerRootName, "");
            doc.setViewPath(replace);
        }

        //文本格式获取文本内容，其他格式无需获取
        String content = null;
        String fileSuffix = getFileSuffix(path);
        if (isText(fileSuffix)) {
            content = readDocContentFromFile(path, false);
            if (null != content) {
                content = content.replaceAll("\t", "");
            }
        }
        doc.setContent(StringUtils.isBlank(content) ? "" : content);


        return Result.success(doc);
    }

    @RequestMapping("/autoSave")
    public Result autoSave(String docId, int docType, String path, String content) {

        // if (docType == 1) {
        boolean flag = saveDocContentToFile(content, path, null);
        if (flag) {
            return Result.success();
        }
        // }

        return Result.fail("自动保存失败！");
    }

    @RequestMapping("/addDoc")
    public Result addDoc(int type, String pid, String path, String name, String content) {
        Doc doc = new Doc();
        doc.setName(name);
        doc.setType(type);
        doc.setContent(content);
        doc.setPath(StringUtils.isBlank(path) ? getOuterRootName() : path);
        if (StringUtils.isBlank(pid) || pid.equals("0")) {
            doc.setPid(buildDocIdByName(getOuterRootName()));
        } else {
            doc.setPid(pid);
        }
        createRealDoc(doc);
        doc.setPath(doc.getPath() + File.separator + doc.getName());
        doc.setId(buildDocIdByName(doc.getPath()));
        return Result.success(doc);
    }

    @RequestMapping("/uploadDoc")
    public Map uploadDoc(String docId, String pid, String path,
                         String name, MultipartFile uploadFile
    ) {

        Map map = new HashMap();
        path = StringUtils.isBlank(path) ? getOuterRootName() : path;
        Doc localDoc = new Doc();
        localDoc.setPid(pid);
        localDoc.setPath(path);
        localDoc.setName(name);
        localDoc.setType(0);
        boolean realDoc = updateRealDoc(localDoc, uploadFile, null, null, null);
        if (realDoc) {
            String foldId = buildDocIdByName(localDoc.getPath());
            localDoc.setId(foldId);
            String parentPath = localDoc.getPath();
            String substring = parentPath;
            int indexOf = parentPath.lastIndexOf("/");
            if (parentPath.endsWith("/")) {
                substring = parentPath.substring(0, indexOf);
            }

            String ppath = substring.replace("\\" + localDoc.getName(), "");
            localDoc.setPid(buildDocIdByName(ppath));
        }
        map.put("data", localDoc);
        map.put("status", true);
        return map;
    }

    @RequestMapping("/checkDocInfo")
    public Map checkDocInfo(String docId, String pid, String path,
                            String name, Integer level, Integer type, Long size, String checkSum,
                            MultipartFile uploadFile,
                            Integer chunkIndex, Integer chunkNum, Integer cutSize, Long chunkSize, String chunkHash) {
        Map map = new HashMap();
        map.put("status", true);
        map.put("code", 200);
        map.put("msg", null);

        path = StringUtils.isBlank(path) ? getOuterRootName() : path;
        Doc localDoc = new Doc();
        localDoc.setId(docId);
        localDoc.setPid(pid);
        localDoc.setPath(path + File.separator + name);
        localDoc.setName(name);
        localDoc.setType(0);

        String localParentPath = localDoc.getPath();
        File localEntry = new File(localParentPath);
        if (localEntry.exists()) {
            map.put("msgData", "0");
            localDoc.setSize(localEntry.length());
            localDoc.setLatestEditTime(localEntry.lastModified());
            localDoc.setType(localEntry.isDirectory() ? 2 : 1);
            if (localDoc.getType() == 1) {
                if (StringUtils.isNotBlank(checkSum)) {
                    String fileMd5 = Md5Util.getFileMd5(localEntry);
                    if (checkSum.equals(fileMd5)) {
                        map.put("msgData", "1");
                    }
                }
            }
        }

        map.put("data", localDoc);

        return map;
    }

    @RequestMapping("/downloadDocPrepare")
    public Map downloadDocPrepare(String docId, String pid, String path, String name, Integer type,
                                  Integer downloadType) {
        Doc doc = new Doc();
        doc.setId(docId);
        doc.setPath(path);
        doc.setName(name);
        doc.setType(type);
        doc.setPid(pid);
        Map map = downloadDocPrepare_FSM(doc);
        return map;
    }


    @RequestMapping("/downloadDoc")
    public void downloadDoc(String targetPath, String targetName,
                            Integer deleteFlag, //是否删除已下载文件  0:不删除 1:删除
                            HttpServletResponse response, HttpServletRequest request) throws Exception {
        Map map = new HashMap();
        map.put("status", false);
        map.put("code", 500);
        if (targetPath == null || targetName == null) {
            map.put("msg", "目标路径不能为空!");
            writeJson(map, response);
            return;
        }

        targetPath = new String(targetPath.getBytes("ISO8859-1"), "UTF-8");
        targetPath = base64Decode(targetPath);
        if (targetPath == null) {
            map.put("msg", "目标路径解码失败!");
            writeJson(map, response);
            return;
        }

        System.out.println("downloadDoc targetPath:" + targetPath + " targetName:" + targetName);

        sendTargetToWebPage(targetPath, map, response, request, false);

        if (deleteFlag != null && deleteFlag == 1) {
            delFileOrDir(targetPath);
        }
    }

    @RequestMapping(value = "/downloadDoc/{targetPath}", method = RequestMethod.GET)
    public void downloadDoc(@PathVariable("targetPath") String targetPath,
                            HttpServletResponse response, HttpServletRequest request) throws Exception {
        Map map = new HashMap();
        map.put("status", false);
        map.put("code", 500);
        if (targetPath == null) {
            map.put("msg", "目标路径不能为空!");
            writeJson(map, response);
            return;
        }
        targetPath = new String(targetPath.getBytes("ISO8859-1"), "UTF-8");
        //双重加密需要双重解密
        targetPath = base64Decode(targetPath);
        targetPath = base64Decode(targetPath);
        if (targetPath == null) {
            map.put("msg", "目标路径解码失败!");
            writeJson(map, response);
            return;
        }
        sendTargetToWebPage(targetPath, map, response, request, false);
    }

    @RequestMapping("/renameDoc")
    public Result renameDoc(String docId, String pid, String path, String name, Integer level, Integer type, String dstName) {
        //获取到当前文件目录
        String dstDirPath = path.substring(0, path.lastIndexOf("\\"));
        //原文件路径
        String oldPath = dstDirPath + File.separator + name;
        //新文件路径
        String newPath = dstDirPath + File.separator + dstName;

        File oldFile = new File(oldPath);
        File newFile = new File(newPath);
        if (newFile.exists()) {
            return Result.fail("文件 " + newPath + " 已存在，重命名失败");
        }

        if (oldFile.exists()) {
            oldFile.renameTo(newFile);
        }
        Doc doc = new Doc();
        doc.setId(docId);
        doc.setPid(pid);
        doc.setName(dstName);
        doc.setPath(newPath);
        doc.setType(type);
        return Result.success(doc);
    }

    @RequestMapping("/deleteDoc")
    public Result deleteDoc(String docId, String pid, String path, String name, Integer type) {
        Doc doc = new Doc();
        doc.setId(docId);
        doc.setName(name);
        doc.setPath(path);
        doc.setPid(pid);
        doc.setType(type);
        delFileOrDir(path);
        return Result.success(doc);
    }

    @RequestMapping("/searchDoc")
    public Result searchDoc(Integer pid, String path,
                            String searchWord, String sort,
                            Integer pageIndex, Integer pageSize) {
        path = StringUtils.isBlank(path) ? getOuterRootName() : path;
        //搜索
        File folder = new File(path);
        List<File> files = searchFiles(folder, searchWord);
        List<Doc> result = new ArrayList<>();
        for (File file : files) {
            String filePath = file.getPath();
            Doc doc = new Doc();
            doc.setPath(filePath);
            doc.setId(buildDocIdByName(filePath));
            doc.setName(file.getName());
            doc.setType(file.isDirectory() ? 2 : 1);
            String[] temp = new String[2];
            seperatePathAndName(filePath, temp);
            doc.setPid(buildDocIdByName(temp[0]));
            result.add(doc);
        }
        if (null != sort) {
            result = sortDocList(result, sort);
        }
        return Result.success(result);
    }


    @RequestMapping("/getZipSubDocList")
    public Result getZipSubDocList(String docPath, String docName) {
        Doc rootDoc = new Doc();
        rootDoc.setName(docName);
        rootDoc.setPath(docPath);
        List<Doc> docList = getZipSubDocList(rootDoc, docPath, docName);
        return Result.success(docList);
    }

    @RequestMapping("/getZipDocFileLink")
    public Result getZipDocFileLink(String path, String name, String rootPath, String rootName) {
        File pFife = new File(rootPath);
        Doc rootDoc = new Doc();
        rootDoc.setPath(rootPath);
        rootDoc.setName(rootName);
        rootDoc.setType(pFife.isDirectory() ? 2 : 1);
        String[] temp = new String[2];
        seperatePathAndName(rootPath, temp);
        rootDoc.setId(buildDocIdByName(rootPath));
        rootDoc.setPid(buildDocIdByName(temp[0]));

        File file = new File(path);
        Doc doc = new Doc();
        doc.setPath(path);
        doc.setName(name);
        doc.setType(file.isDirectory() ? 2 : 1);
        String[] temp1 = new String[2];
        seperatePathAndName(rootPath, temp1);
        doc.setId(buildDocIdByName(path));
        doc.setPid(rootDoc.getId());
        checkAndExtractEntryFromCompressDoc(rootDoc, doc);
        String urlSafe = base64EncodeURLSafe(doc.getViewPath());
        return Result.success(urlSafe);
    }
}
